package com.hujing.springsource.a15;

import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyConfig;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

/**
 * Spring的代理选择,在这个例子中我们可以学到以下知识:
 * 1.Spring的代理选择
 * 2.底层的切点实现
 * 3.底层的通知实现
 * 4.ProxyFactory是用来创建代理的核心实现,用AopProxyFactory选择具体代理实现
 *  -JdkDynamicAopProxy
 *  -ObjenesisCglibAopProxy
 */
public class A15 {

    public static void main(String[] args) {
        // 1.准备切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");

        // 2.准备通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before");
            Object result = invocation.proceed();// 调用目标方法
            System.out.println("after");
            return result;
        };

        // 3.准备切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        /**4.创建代理,具体是使用jdk实现还是cglib实现,遵循以下的规则:
         * 1.ProxyConfig中的proxyTargetClass=false,目标实现了接口,用jdk实现
         * 2.ProxyConfig中的proxyTargetClass=false,目标没有实现接口,用cglib实现
         * 3.ProxyConfig中的proxyTargetClass=true,总是使用cglib实现
         */
        Target1 target1 = new Target1();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target1);
        proxyFactory.addAdvisor(advisor);
        T1 proxy = (T1) proxyFactory.getProxy();
        
        // 5.调用目标方法
        proxy.foo();
        proxy.bar();
    }
    
    interface T1{
        void foo();
        void bar();
    }
    
    static class Target1 implements T1{

        @Override
        public void foo() {
            System.out.println("Target1 foo()");
        }

        @Override
        public void bar() {
            System.out.println("Target1 bar()");
        }
    }
}
